#pragma once

#include <string>
#include <cstdlib>

#include "Socket.hpp"
#include "MathProtocol.hpp"

class TCPServer{
public:
    TCPServer(uint16_t port) : _port(port){};

    void Init(){
        _listenSock.Sock();
        _listenSock.Bind(_port);
        _listenSock.Listen();
    }

    void Start(){
        while(true){
            std::string clientIP;
            uint16_t clientPort;
            int clientSockfd = _listenSock.Accept(clientIP, clientPort);
            if(clientSockfd < 0){ continue; }
            // std::cout << "Accept over" << std::endl;
            
            //服务开始(子进程进行服务)
            pid_t pid = fork();
            if(pid == 0){//子进程
                // std::cout << "子进程开始" << std::endl;
                HandlerClient(clientSockfd);
                close(clientSockfd);
                exit(0);
            }else if(pid > 0){
                //父进程关闭fd，并退出
                close(clientSockfd);
            }else{//fork失败
                close(clientSockfd);
            }
        }
    }

private:
    uint16_t _port;
    TCPSocket _listenSock;

    //子进程执行的方法
    void HandlerClient(int clientSockfd){
        //执行客户端方法
        // std::cout << "HandlerClient" << std::endl;
        //创建协议
        uint8_t buffer[1024];
        while(true){
            int received = recv(clientSockfd, buffer, sizeof(buffer), 0);
            if(received <= 0){
                break;
            }

            if(!MathProtocol::validateMessage(buffer, received)){
                auto error = MathProtocol::CreateError(MathProtocol::ErrorCode::INVALID_FORMAT
                , MathProtocol::GetErrorDescription(MathProtocol::ErrorCode::INVALID_FORMAT));
                send(clientSockfd, error.data(), error.size(), 0);
                continue;
            }

            MathProtocol::RequestMessage request;
            if(!MathProtocol::ParseRequest(buffer, received, request)){
                auto error = MathProtocol::CreateError(MathProtocol::ErrorCode::PROTOCOL_ERROR
                , MathProtocol::GetErrorDescription(MathProtocol::ErrorCode::PROTOCOL_ERROR));
                send(clientSockfd, error.data(), error.size(), 0);
                continue;
            }
            
            //走到这里已经解析成功了
            std::cout << "计算：" << request.operand1
            << " " << MathProtocol::GetOperationName(request.operation) << " "
            << request.operand2;
            
            std::pair<MathProtocol::ErrorCode, double> result = 
            MathProtocol::ExecuteOperation(request.operation, 
            request.operand1, request.operand2);

            if(result.first == MathProtocol::ErrorCode::SUCCESS){
                auto response = MathProtocol::CreateResponse(result.first, result.second);
                send(clientSockfd, response.data(), response.size(), 0);
                std::cout << " = " << result.second << std::endl;
            }else{
                auto error = MathProtocol::CreateError(result.first, 
                MathProtocol::GetErrorDescription(result.first));
                send(clientSockfd, error.data(), error.size(), 0);
                std::cout << " 错误: " << MathProtocol::GetErrorDescription(result.first) << std::endl;
            }
        }

        close(clientSockfd);
    }
};